using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Windows.Forms;
using Microsoft.Vsts.Ranger.Migration.TfsToTfs;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
//using Microsoft.Vsts.Ranger.Migration.TfsToTfs.Client;
using Microsoft.Vsts.Ranger.Migration.TfsToTfs.Service.Services;

namespace Microsoft.Vsts.Ranger.Migration.TfsToTfs.Client.Common
{
    class SessionFileManager
    {
        private MigrationConfig.MigrationElement migrationConfig;

        public MigrationConfig.MigrationElement MigrationConfig
        {
            get { return migrationConfig; }
        }


        public void LoadMigrationConfig()
        {
            MigrationService client = new MigrationService();
            try
            {
                string configFile = client.GetConfigFileContents();

                if (configFile == null)
                    throw new ArgumentException(
                        "The server did not return any configuration file information. Check the server log.");

                XmlSerializer ser = new XmlSerializer(typeof(MigrationConfig.MigrationElement));

                using (StringReader reader = new StringReader(configFile))
                {
                    migrationConfig = (MigrationConfig.MigrationElement)ser.Deserialize(reader);
                }
            }
            catch (TimeoutException timeout)
            {
                ExceptionManager.DisplayExceptionToUser(timeout, "The service operation timed out. ");
                //client.Abort();
            }
            /*
            catch (FaultException serverError) //TODO: Need to use <ServerError> here
            {
                ExceptionManager.DisplayExceptionToUser(serverError, serverError.ToString());
                client.Abort();
            }*/
            catch (EndpointNotFoundException noEndpoint)
            {
                ExceptionManager.DisplayExceptionToUser(noEndpoint, "The configured EndPoint was not found, "
                                                                        + "check the configuration and make sure the service is started.");
                //client.Abort();
            }
            catch (FaultException unknownFault)
            {
                ExceptionManager.DisplayExceptionToUser(unknownFault, "An unknown exception was received.");
                //client.Abort();
            }
            catch (CommunicationException communicationException)
            {
                ExceptionManager.DisplayExceptionToUser(communicationException, "There was a communication problem.");
                //client.Abort();
            }
        }

  

        public void LoadTemplateConfig()
        {
            MigrationService client = new MigrationService();

            try
            {
                string configFile = client.GetTemplateFileContents();

                if (configFile == null)
                    throw new ArgumentException(
                        "The server did not return any template configuration file information. Check the server log.");

                XmlSerializer ser = new XmlSerializer(typeof (MigrationConfig.MigrationElement));

                StringReader reader = new StringReader(configFile);

                migrationConfig = (MigrationConfig.MigrationElement) ser.Deserialize(reader);

                reader.Close();
            }
            catch (TimeoutException timeout)
            {
                ExceptionManager.DisplayExceptionToUser(timeout, "The service operation timed out. ");
                //client.Abort();
            }
            /*
            catch (FaultException serverError) //TODO: Need to use <ServerError> here
            {
                ExceptionManager.DisplayExceptionToUser(serverError, serverError.ToString());
                client.Abort();
            }*/
            catch (FaultException unknownFault)
            {
                ExceptionManager.DisplayExceptionToUser(unknownFault, "An unknown exception was received.");
                //client.Abort();
            }
            catch (CommunicationException communicationException)
            {
                ExceptionManager.DisplayExceptionToUser(communicationException, "There was a communication problem.");
                //client.Abort();
            }
        }

        public MigrationConfig.VCSessionElement AddVersionControlSession(MigrationConfig.VCSessionElement vcSection)
        {
            migrationConfig.VC.Sessions.Add(vcSection);

            return migrationConfig.VC.Sessions[0];

        }

        public void AddWorkItemTrackingSection(MigrationConfig.WITSessionElement witSection)
        {
            migrationConfig.WIT.Sessions.Add(witSection);
        }

        public void AddServerSectionIfMissing(string serverName, string serverUri, bool useStoredCredential)
        {
            if (serverUri == null)
                throw new ArgumentException("A serverUri must be specified when adding a new Server.");

            bool found = false;

//            string hostName = GetHostNameFromServerName(serverName).ToLower();

            foreach (MigrationConfig.ServerElement section in migrationConfig.Servers)
                if (section.id.ToUpper() == serverName.ToUpper())
                    found = true;

            if (!found)
            {
                MigrationConfig.ServerElement newSection = new MigrationConfig.ServerElement();
                newSection.id = serverName;
                newSection.Server = serverUri;

                if (useStoredCredential)
                {
                    newSection.UseStoredCredentials = true.ToString();
                }

                migrationConfig.Servers.Add(newSection);
            }
        }

        public void DeleteSession(string sessionId)
        {
            foreach (MigrationConfig.VCSessionElement vcSection in this.MigrationConfig.VC.Sessions)
                if (vcSection.id == sessionId)
                {
                    this.MigrationConfig.VC.Sessions.Remove(vcSection);

                    //If this was the last session, remove the whole VC section
                    if (this.migrationConfig.VC.Sessions.Count == 0)
                        this.migrationConfig.VC = null;

                    return;
                }

            foreach (MigrationConfig.WITSessionElement witSection in this.MigrationConfig.WIT.Sessions)
                if (witSection.id == sessionId)
                {
                    this.MigrationConfig.WIT.Sessions.Remove(witSection);

                    //If this was the last session, remove the whole WIT section
                    if (this.migrationConfig.WIT.Sessions.Count == 0)
                        this.migrationConfig.WIT = null;

                    return;
                }


            throw new Exception("Session specified was not located.");
        }

        public void SaveFileChanges()
        {Microsoft.Vsts.Ranger.Migration.TfsToTfs.Service.Services.
            MigrationService client = new MigrationService();
            
            try
            {
                string fileContents = GetConfigFileContents();

                client.SaveConfigFile(fileContents);
            }
            catch (TimeoutException timeout)
            {
                ExceptionManager.DisplayExceptionToUser(timeout, "The service operation timed out. ");
                //client.Abort();
            }
            /*
            catch (FaultException serverError) //TODO: Need to use <ServerError> here
            {
                ExceptionManager.DisplayExceptionToUser(serverError, serverError.ToString());
                client.Abort();
            }*/
            catch (FaultException unknownFault)
            {
                ExceptionManager.DisplayExceptionToUser(unknownFault, "An unknown exception was received.");
                //client.Abort();
            }
            catch (CommunicationException communicationException)
            {
                ExceptionManager.DisplayExceptionToUser(communicationException, "There was a communication problem.");
                //client.Abort();
            }

        }

        private string GetHostNameFromServerName(string serverName)
        {
            if (Uri.IsWellFormedUriString(serverName, UriKind.Absolute))
            {
                Uri uri = new Uri(serverName);

                return uri.Host;
            }
            else
            {
                return serverName;
            }
        }

        private string GetConfigFileContents()
        {
            XmlSerializer ser = new XmlSerializer(typeof(MigrationConfig.MigrationElement));

            
            string fileName = Path.GetTempFileName();

            TextWriter outStream = File.CreateText(fileName);
            ser.Serialize(outStream, migrationConfig);

            outStream.Close();

            return File.ReadAllText(fileName);
        }
    }
}
